
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        .price-up {
            background: linear-gradient(45deg, #4caf50, #8bc34a);
            animation: pulseGreen 0.6s ease-out;
        }
        
        .price-down {
            background: linear-gradient(45deg, #f44336, #ff5722);
            animation: pulseRed 0.6s ease-out;
        }
        
        .flash-up {
            animation: flashGreen 1s ease-out;
        }
        
        .flash-down {
            animation: flashRed 1s ease-out;
        }
        
        @keyframes pulseGreen {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }
        
        @keyframes pulseRed {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }
        
        @keyframes flashGreen {
            0% { background-color: rgba(76, 175, 80, 0.3); }
            100% { background-color: transparent; }
        }
        
        @keyframes flashRed {
            0% { background-color: rgba(244, 67, 54, 0.3); }
            100% { background-color: transparent; }
        }
        
        .order-row {
            transition: all 0.3s ease;
        }
        
        .depth-bar {
            transition: width 0.5s ease;
        }
        
        .slide-in {
            animation: slideIn 0.4s ease-out;
        }
        
        @keyframes slideIn {
            from { transform: translateX(-100%); opacity: 0; }
            to { transform: translateX(0); opacity: 1; }
        }
        
        .ticker-pulse {
            animation: tickerPulse 2s infinite;
        }
        
        @keyframes tickerPulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.7; }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-gray-900 to-gray-800 min-h-screen text-white">
    <div class="container mx-auto px-4 py-8">
        <!-- 头部 -->
        <div class="flex justify-between items-center mb-8">
            <div class="flex items-center space-x-4">
                <div class="bg-gray-800 rounded-lg px-4 py-2">
                    <div class="text-sm text-gray-400">最后更新</div>
                    <div id="lastUpdate" class="text-lg font-semibold">00:00:00</div>
                </div>
            </div>
        </div>

        <!-- 主要指标 -->
        <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
            <div class="bg-gray-800 rounded-xl p-6 shadow-lg">
                <div class="flex justify-between items-center">
                    <div>
                        <div class="text-gray-400 text-sm">当前价格</div>
                        <div id="currentPrice" class="text-2xl font-bold text-green-400">$45,678.90</div>
                    </div>
                    <i class="fas fa-dollar-sign text-2xl text-green-400"></i>
                </div>
            </div>
            
            <div class="bg-gray-800 rounded-xl p-6 shadow-lg">
                <div class="flex justify-between items-center">
                    <div>
                        <div class="text-gray-400 text-sm">24h涨跌幅</div>
                        <div id="priceChange" class="text-2xl font-bold text-green-400">+2.34%</div>
                    </div>
                    <i class="fas fa-arrow-up text-2xl text-green-400"></i>
                </div>
            </div>
            
            <div class="bg-gray-800 rounded-xl p-6 shadow-lg">
                <div class="flex justify-between items-center">
                    <div>
                        <div class="text-gray-400 text-sm">24h成交量</div>
                        <div id="volume24h" class="text-xl font-bold text-white">1,245 BTC</div>
                    </div>
                    <i class="fas fa-exchange-alt text-2xl text-blue-400"></i>
                </div>
            </div>
            
            <div class="bg-gray-800 rounded-xl p-6 shadow-lg">
                <div class="flex justify-between items-center">
                    <div>
                        <div class="text-gray-400 text-sm">市场深度</div>
                        <div id="marketDepth" class="text-xl font-bold text-white">$2.8M</div>
                    </div>
                    <i class="fas fa-layer-group text-2xl text-purple-400"></i>
                </div>
            </div>
        </div>

        <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
            <!-- 买单盘口 -->
            <div class="bg-gray-800 rounded-xl shadow-2xl overflow-hidden">
                <div class="bg-green-600 px-6 py-4">
                    <h2 class="text-xl font-bold text-white">
                        <i class="fas fa-arrow-down mr-2"></i>
                        bid
                    </h2>
                </div>
                <div class="p-6">
                    <div class="flex justify-between text-sm text-gray-400 mb-4">
                        <span>价格 (USD)</span>
                        <span>数量 (BTC)</span>
                        <span>总计 (USD)</span>
                    </div>
                    <div id="bidOrders" class="space-y-2">
                    </div>
                </div>
            </div>

            <!-- 卖单盘口 -->
            <div class="bg-gray-800 rounded-xl shadow-2xl overflow-hidden">
                <div class="bg-red-600 px-6 py-4">
                    <h2 class="text-xl font-bold text-white">
                        <i class="fas fa-arrow-up mr-2"></i>
                        ask
                    </h2>
                </div>
                <div class="p-6">
                    <div class="flex justify-between text-sm text-gray-400 mb-4">
                        <span>价格 (USD)</span>
                        <span>数量 (BTC)</span>
                        <span>总计 (USD)</span>
                    </div>
                    <div id="askOrders" class="space-y-2">
                    </div>
                </div>
            </div>
        </div>

        <!-- 最新成交 -->
        <div class="mt-8 bg-gray-800 rounded-xl shadow-2xl overflow-hidden">
            <div class="bg-blue-600 px-6 py-4">
                <h2 class="text-xl font-bold text-white">
                        <i class="fas fa-history mr-2"></i>
                        最新成交
                    </h2>
                </div>
                <div class="p-6">
                    <div id="recentTrades" class="space-y-2">
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        class OrderBook {
            constructor() {
                this.bidOrders = [];
                this.askOrders = [];
                this.recentTrades = [];
                this.currentPrice = 45678.90;
                this.initializeData();
            }

            initializeData() {
                this.bidOrders = [
                    { price: 45670.50, amount: 1.25, total: 57088.13 },
                    { price: 45665.80, amount: 0.85, total: 38816.93 },
                    { price: 45660.20, amount: 2.10, total: 95886.42 },
                    { price: 45655.40, amount: 1.50, total: 68483.10 },
                    { price: 45650.60, amount: 0.75, total: 34237.95 },
                    { price: 45645.30, amount: 1.20, total: 54774.36 },
                    { price: 45640.10, amount: 0.95, total: 43358.10 },
                    { price: 45635.70, amount: 1.80, total: 82144.26 },
                    { price: 45630.90, amount: 0.60, total: 27378.54 },
                    { price: 45625.40, amount: 1.10, total: 50187.94 },
                    { price: 45620.20, amount: 0.85, total: 38777.17 },
                    { price: 45615.60, amount: 1.30, total: 59300.28 }
                ];

                this.askOrders = [
                    { price: 45685.20, amount: 0.90, total: 41116.68 },
                    { price: 45690.40, amount: 1.15, total: 52543.96 },
                    { price: 45695.60, amount: 0.80, total: 36556.48 },
                    { price: 45700.80, amount: 1.25, total: 57126.00 },
                    { price: 45705.30, amount: 1.40, total: 63987.42 },
                    { price: 45710.70, amount: 0.95, total: 43425.17 },
                    { price: 45715.40, amount: 1.10, total: 50286.94 },
                    { price: 45720.90, amount: 0.75, total: 34290.68 },
                    { price: 45725.60, amount: 1.30, total: 59443.28 },
                    { price: 45730.20, amount: 1.05, total: 48016.71 },
                    { price: 45735.80, amount: 0.85, total: 38875.43 },
                    { price: 45740.40, amount: 1.20, total: 54888.48 },
                    { price: 45745.70, amount: 0.95, total: 43458.42 }
                ];

                this.recentTrades = [
                    { price: 45678.90, amount: 0.25, time: '14:50:23', type: 'buy' },
                    { price: 45675.60, amount: 0.18, time: '14:50:15', type: 'sell' },
                    { price: 45680.40, amount: 0.32, time: '14:50:08', type: 'buy' },
                    { price: 45672.30, amount: 0.45, time: '14:50:01', type: 'buy' },
                    { price: 45685.10, amount: 0.28, time: '14:49:55', type: 'sell' },
                    { price: 45670.80, amount: 0.15, time: '14:49:48', type: 'sell' },
                    { price: 45688.50, amount: 0.22, time: '14:49:42', type: 'buy' },
                    { price: 45665.40, amount: 0.35, time: '14:49:36', type: 'buy' }
                ];
            }

            generateRandomOrder() {
                const isBid = Math.random() > 0.5;
                const basePrice = this.currentPrice;
                const priceVariation = (Math.random() - 0.5) * 100;
                
                const newOrder = {
                    price: parseFloat((basePrice + priceVariation).toFixed(2)),
                    amount: parseFloat((Math.random() * 2).toFixed(2)),
                    total: 0,
                    type: isBid ? 'bid' : 'ask'
                };
                
                newOrder.total = parseFloat((newOrder.price * newOrder.amount).toFixed(2));
                
                if (isBid) {
                    this.bidOrders.unshift(newOrder);
                    if (this.bidOrders.length > 10) this.bidOrders.pop();
                } else {
                    this.askOrders.unshift(newOrder);
                    if (this.askOrders.length > 10) this.askOrders.pop();
                }
                
                return newOrder;
            }

            updatePrice(newPrice) {
                const oldPrice = this.currentPrice;
                this.currentPrice = newPrice;
                
                this.bidOrders.forEach(order => {
                    if (Math.random() > 0.7) {
                        order.price = parseFloat((newPrice + (Math.random() - 0.5) * 50).toFixed(2));}
                    order.total = parseFloat((order.price * order.amount).toFixed(2));
                });
                
                this.askOrders.forEach(order => {
                    if (Math.random() > 0.7) {
                        order.price = parseFloat((newPrice + (Math.random() - 0.3) * 50).toFixed(2));}
                    order.total = parseFloat((order.price * order.amount).toFixed(2));
                });
                
                return {
                    oldPrice,
                    newPrice,
                    change: newPrice - oldPrice,
                    changePercent: ((newPrice - oldPrice) / oldPrice * 100).toFixed(2)
                };
            }

            generateTrade() {
                const isBuy = Math.random() > 0.5;
                const priceVariation = (Math.random() - 0.5) * 100;
                const tradePrice = parseFloat((this.currentPrice + priceVariation).toFixed(2));
                
                const newTrade = {
                    price: tradePrice,
                    amount: parseFloat((Math.random() * 0.5).toFixed(2)),
                    time: new Date().toLocaleTimeString(),
                    type: isBuy ? 'buy' : 'sell'
                };
                
                this.recentTrades.unshift(newTrade);
                if (this.recentTrades.length > 20) this.recentTrades.pop();
                
                return newTrade;
            }

            getBidOrders() {
                return this.bidOrders.slice(0, 10);
            }

            getAskOrders() {
                return this.askOrders.slice(0, 10);
            }

            getRecentTrades() {
                return this.recentTrades.slice(0, 8);
            }
        }

        class PriceAnimation {
            constructor() {
                this.animationQueue = [];
                this.isAnimating = false;
            }

            addPriceChange(oldPrice, newPrice, element) {
                this.animationQueue.push({
                    oldPrice,
                    newPrice,
                    element,
                    timestamp: Date.now()
                });
                
                if (!this.isAnimating) {
                    this.processQueue();
                }
            }

            processQueue() {
                if (this.animationQueue.length === 0) {
                    this.isAnimating = false;
                    return;
                }
                
                this.isAnimating = true;
                const animation = this.animationQueue.shift();
                
                const animationClass = newPrice > oldPrice ? 'price-up' : 'price-down';
                animation.element.classList.add(animationClass);
                
                setTimeout(() => {
                    animation.element.classList.remove('price-up', 'price-down');
                    this.processQueue();
                }, 600);
            }

            flashElement(element, type) {
                const flashClass = type === 'up' ? 'flash-up' : 'flash-down';
                element.classList.add(flashClass);
                
                setTimeout(() => {
                    element.classList.remove('flash-up', 'flash-down');
                }, 1000);
            }

            createSlideInAnimation(element) {
                element.classList.add('slide-in');
                
                setTimeout(() => {
                    element.classList.remove('slide-in');
                }, 400);
            }

            animateDepthBar(element, newWidth) {
                element.style.width = newWidth + '%';
            }

            pulseTicker(element) {
                element.classList.add('ticker-pulse');
                
                setTimeout(() => {
                    element.classList.remove('ticker-pulse');
                }, 2000);
            }

            createOrderElement(order, isBid) {
                const div = document.createElement('div');
                div.className = `order-row flex justify-between items-center p-3 rounded-lg ${
                        isBid ? 'bg-green-900/30' : 'bg-red-900/30'
                    } transition-all duration-300`;
                
                const depthPercentage = (order.amount / 2.5) * 100;
                
                div.innerHTML = `
                    <div class="flex items-center w-full">
                        <div class="depth-bar h-4 rounded-l ${
                            isBid ? 'bg-green-500/50' : 'bg-red-500/50'
                        }" style="width: ${depthPercentage}%"></div>
                        <div class="flex justify-between w-full text-sm">
                            <span class="font-mono ${
                                isBid ? 'text-green-400' : 'text-red-400'
                        }">$${order.price.toLocaleString()}</span>
                            <span class="font-mono">${order.amount}</span>
                            <span class="font-mono">$${(order.total).toLocaleString()}</span>
                        </div>
                    </div>
                `;
                
                return div;
            }
        }

        class TradingApp {
            constructor() {
                this.orderBook = new OrderBook();
                this.animation = new PriceAnimation();
                this.isRunning = false;
                this.updateInterval = null;
                this.init();
            }

            init() {
                this.renderAll();
                this.startAutoUpdate();
                this.setupEventListeners();
            }

            renderAll() {
                this.renderBidOrders();
                this.renderAskOrders();
                this.renderRecentTrades();
                this.updateStats();
            }

            renderBidOrders() {
                const container = document.getElementById('bidOrders');
                container.innerHTML = '';
                
                const bidOrders = this.orderBook.getBidOrders();
                bidOrders.forEach(order => {
                    const orderElement = this.animation.createOrderElement(order, true);
                    container.appendChild(orderElement);
                });
            }

            renderAskOrders() {
                const container = document.getElementById('askOrders');
                container.innerHTML = '';
                
                const askOrders = this.orderBook.getAskOrders();
                askOrders.forEach(order => {
                    const orderElement = this.animation.createOrderElement(order, false);
                    container.appendChild(orderElement);
                });
            }

            renderRecentTrades() {
                const container = document.getElementById('recentTrades');
                container.innerHTML = '';
                
                const recentTrades = this.orderBook.getRecentTrades();
                recentTrades.forEach(trade => {
                    const tradeElement = this.createTradeElement(trade);
                    container.appendChild(tradeElement);
                });
            }

            createTradeElement(trade) {
                const div = document.createElement('div');
                div.className = `flex justify-between items-center p-2 rounded text-sm ${
                        trade.type === 'buy' ? 'bg-green-900/20' : 'bg-red-900/20'
                    } transition-all duration-300`;
                
                div.innerHTML = `
                    <span class="font-mono ${
                        trade.type === 'buy' ? 'text-green-400' : 'text-red-400'
                }">$${trade.price.toLocaleString()}</span>
                    <span class="font-mono">${trade.amount}</span>
                    <span class="text-gray-400">${trade.time}</span>
                    <span class="px-2 py-1 rounded text-xs ${
                        trade.type === 'buy' ? 'bg-green-600' : 'bg-red-600'
                }">${trade.type === 'buy' ? '买入' : '卖出'}</span>
                `;
                
                return div;
            }

            updateStats() {
                const now = new Date();
                document.getElementById('lastUpdate').textContent = 
                    now.toLocaleTimeString();
                
                const priceElement = document.getElementById('currentPrice');
                const oldPrice = parseFloat(priceElement.textContent.replace(/[$,]/g, ''));
                const newPrice = this.orderBook.currentPrice;
                
                priceElement.textContent = `$${newPrice.toLocaleString()}`;
                
                if (oldPrice !== newPrice) {
                    this.animation.addPriceChange(oldPrice, newPrice, priceElement);
                    
                    const changeElement = document.getElementById('priceChange');
                    const change = ((newPrice - oldPrice) / oldPrice * 100).toFixed(2);
                    changeElement.textContent = `${change > 0 ? '+' : ''}${change}%`;
                    changeElement.className = `text-2xl font-bold ${
                        change > 0 ? 'text-green-400' : 'text-red-400'
                    }`;
                }
                const volumeElement = document.getElementById('volume24h');
                const newVolume = parseFloat(volumeElement.textContent) + Math.random() * 0.1;
                volumeElement.textContent = `${newVolume.toFixed(3)} BTC`;
                
                const depthElement = document.getElementById('marketDepth');
                const newDepth = (Math.random() * 0.5 + 2.5).toFixed(1);
                depthElement.textContent = `$${newDepth}M`;
            }

            simulateMarketMovement() {
                const volatility = 0.002;
                const randomWalk = (Math.random() - 0.5) * volatility;
                const newPriceValue = this.orderBook.currentPrice * (1 + randomWalk);
                
                const updateResult = this.orderBook.updatePrice(newPriceValue);
                
                this.orderBook.generateRandomOrder();
                
                this.orderBook.generateTrade();
                
                this.renderAll();
                
                const priceElement = document.getElementById('currentPrice');
                this.animation.flashElement(priceElement, updateResult.change > 0 ? 'up' : 'down');
            }

            startAutoUpdate() {
                this.isRunning = true;
                this.updateInterval = setInterval(() => {
                    this.simulateMarketMovement();
                }, 1500);
            }

            stopAutoUpdate() {
                this.isRunning = false;
                if (this.updateInterval) {
                    clearInterval(this.updateInterval);
                    this.updateInterval = null;
                }
            }

            setupEventListeners() {
                document.addEventListener('keydown', (e) => {
                    if (e.key === ' ') {
                        if (this.isRunning) {
                            this.stopAutoUpdate();
                        } else {
                            this.startAutoUpdate();
                        }
                    }
                });
                
                window.addEventListener('focus', () => {
                    if (!this.isRunning) {
                        this.startAutoUpdate();
                    }
                });
                
                window.addEventListener('blur', () => {
                    if (this.isRunning) {
                        this.stopAutoUpdate();
                    }
                });
            }
        }

        document.addEventListener('DOMContentLoaded', () => {
            window.tradingApp = new TradingApp();
        });
    </script>
</body>
</html>
